package es.deusto.ingenieria.is.gemas;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import es.deusto.ingenieria.is.csp.algorithm.CSPAlgorithm;
import es.deusto.ingenieria.is.csp.formulation.CSPproblem;
import es.deusto.ingenieria.is.csp.formulation.Variable;

public class GemasProblem extends CSPproblem<Gema>{
	public GemasProblem(List<Ranura> locks) {
		for (Ranura l : locks) {
			this.addVariable(l);
		}
		this.createConstraints();
	}

	private void createConstraints() {
		SumaIgual s = new SumaIgual( "Suma", this.getVariables());
		AllDiff d = new AllDiff(this.getVariables(), "Different");
		for (Variable<Gema> v : this.getVariables()) {
			v.addConstraint(s);
			v.addConstraint(d);
		}
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		List<Variable<Gema>> gems = this.getVariables();
		for (int i = 0; i < gems.size(); i++) {
			if (i % 4 == 0) {
				sb.append('\n');
				sb.append("Cerradura ");
				sb.append((i / 4) + 1);
				sb.append(": \n");
			}
			Gema l = gems.get(i).getValue();
			sb.append(l.toString()).append('\n');
		}
		sb.append('\n');
		return sb.toString();
	}

	public static boolean checkPreconditions(List<Gema> gemas) {
		List<String> colors = new ArrayList<String>(4);
		int weight = 0;
		for (Gema g : gemas) {
			if (!colors.contains(g.getColor())) {
				colors.add(g.getColor().toString());
			}
			weight += g.getWeight();
		}
		System.out.println("Numero de colores diferentes: " + colors.size());
		System.out.println("\nValor total: " + weight);
		if ((weight % 3 != 0) || (colors.size() < 4)) {
			System.out.println("\nNO se cumplen las precondiciones.");
			System.out.println("Solucion NO encontrada");
			return false;
		} else {
			return true;
		}
	}

	public void solve(CSPAlgorithm<Gema> algorithm) {
		SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss.S");
		Date beginDate = GregorianCalendar.getInstance().getTime();
		System.out.println("\nComienzo '" + algorithm.getClass().getName()
				+ "' (" + formatter.format(beginDate) + ")");
		boolean solutionFound = algorithm.solve(this);
		Date endDate = GregorianCalendar.getInstance().getTime();
		System.out.println("Fin   '" + algorithm.getClass().getName() + "' ("
				+ formatter.format(endDate) + ")");

		long miliseconds = (int) Math.abs(beginDate.getTime()
				- endDate.getTime());
		long seconds = miliseconds / 1000;
		miliseconds %= 1000;
		long minutes = seconds / 60;
		seconds %= 60;
		long hours = minutes / 60;
		minutes %= 60;

		String time = "\n* Serach lasts: ";
		time += (hours > 0) ? hours + " h " : " ";
		time += (minutes > 0) ? minutes + " m " : " ";
		time += (seconds > 0) ? seconds + "s " : " ";
		time += (miliseconds >= 0) ? miliseconds + "ms " : " ";

		System.out.println(time);

		if (solutionFound) {
			System.out.println("\nSolucion encontrada");
			System.out.println("\n" + this);
		} else {
			System.out.println("\nSolucion no encontrada");
		}
	}
	
}
